package com.immortal.module;

import com.immortal.core.configure.ImConfig;
import com.immortal.module.oauth.AuthorizationServerConfiguration;
import com.immortal.module.oauth.ResourceServerConfiguration;
import com.immortal.module.oauth.authorize.provider.AuthAuthorizeConfigProvider;
import com.immortal.module.oauth.exception.CustomWebResponseExceptionTranslator;
import com.immortal.module.oauth.handler.ErrorMessageHandler;
import com.immortal.module.oauth.token.TokenStoreConfig;
import com.immortal.module.security.SecurityWebMvcAutoConfiguration;
import com.immortal.module.security.handler.*;
import com.immortal.module.security.userDetail.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.session.HttpSessionEventPublisher;

@Configuration
@Import({SecurityWebMvcAutoConfiguration.class, TokenStoreConfig.class, AuthorizationServerConfiguration.class, ResourceServerConfiguration.class})
public class InitConfig {
    @Autowired
    private ImConfig config;
    @ConditionalOnMissingBean
    @Bean
    ErrorMessageHandler errorMessageHandler(){
        return new ErrorMessageHandler() {
            @Override
            public String handlerError(OAuth2Exception e) {
                return e.getMessage();
            }
        };
    }
    @Bean
    CustomWebResponseExceptionTranslator customWebResponseExceptionTranslator(ErrorMessageHandler errorMessageHandler){
        return new CustomWebResponseExceptionTranslator(errorMessageHandler);
    }
    @ConditionalOnMissingBean
    @Bean
    @Order(Integer.MAX_VALUE - 1)
    AuthAuthorizeConfigProvider authAuthorizeConfigProvider(){
        return new AuthAuthorizeConfigProvider();
    }

    @ConditionalOnMissingBean
    @Bean
    AuthenticationEntryPoint authenticationEntryPoint() {
        return new CustomAuthenticationEntryPoint(config.getLoginFormUrl() == null ? "/login" : config.getLoginFormUrl());
    }

    @ConditionalOnMissingBean
    @Bean
    AccessDeniedHandler accessDeniedHandler() {
        return new CustomAccessDeniedHandler();
    }

    @ConditionalOnMissingBean
    @Bean
    AuthenticationFailureHandler authenticationFailureHandler() {
        return new AuthenticationFailureHandler();
    }

    @ConditionalOnMissingBean
    @Bean
    protected UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }

    @ConditionalOnMissingBean
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @ConditionalOnMissingBean
    @Bean
    AuthenticationLogoutSuccessHandler authenticationLogoutSuccessHandler() {
        return new AuthenticationLogoutSuccessHandler();
    }

    @ConditionalOnMissingBean
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }

    @ConditionalOnMissingBean
    @Bean
    AuthenticationSuccessHandler authenticationSuccessHandler() {
        return new AuthenticationSuccessHandler();
    }
    @ConditionalOnMissingBean
    @Bean
    OauthTokenService oauthTokenService(){
        return new OauthTokenService();
    }
}
